package tpenchere.ui;
import javax.swing.JFrame;
import javax.swing.JMenuBar;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JSeparator;
import javax.swing.AbstractAction;
import javax.swing.JToolBar;

import java.awt.event.ActionEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.swing.Action;
import java.awt.event.ActionListener;
import javax.swing.JEditorPane;

import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Window;
import java.util.Hashtable;
import java.util.LinkedHashMap;
import java.util.Locale;
import java.util.Map;
import java.awt.Frame;
import javax.swing.JPanel;

import tpenchere.application.MainApplication;
import tpenchere.controllers.ControllerInterface;
import tpenchere.controllers.MainWindowController;
import tpenchere.service.MainContext;
import tpenchere.service.SessionHolder;
import tpenchere.ui.contents.*;
import tpenchere.ui.menuBar.DefaultMenuBar;
import tpenchere.ui.menuBar.LoggedMenuBar;

import javax.swing.JLabel;

import org.hsqldb.lib.HashMap;
import org.jdesktop.application.FrameView;
import org.jdesktop.application.ResourceMap;
import org.jdesktop.application.SingleFrameApplication;
import org.springframework.util.StringUtils;


public class MainWindow extends FrameView {
	public static final String HOME_PANEL = "home_panel";
	public static final String LOGIN_PANEL = "login_panel";
	public static final String REGISTER_PANEL = "register_panel";
	
	private String currentPanel = HOME_PANEL;
	private AbstractView currentView;
	private MainWindowController controller;
	
	private final ResourceMap resourceMap = MainApplication.getApplication().getContext().getResourceMap(this.getClass());
	
	// Menubar
	private DefaultMenuBar defaultMenuBar;
	private LoggedMenuBar loggedMenuBar;
	
	// Views
	private Map<String, AbstractView> cachedViews = new LinkedHashMap<String, AbstractView>();
	private AbstractView login;
	private AbstractView register;
	private AbstractView home;

	private final Action action = new Quit();
	
	public MainWindow(SingleFrameApplication pApp) {
		super(pApp);
		getFrame().addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent pE) {
                // use BSAF to exit application
                MainApplication.getApplication().exit();
            }
        });
        // close operation is overrided by WindowListener
        getFrame().setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
        
        controller = new MainWindowController(this);
        MainContext.init(controller);
        
		defaultMenuBar = new DefaultMenuBar(resourceMap, controller);
		this.setMenuBar(defaultMenuBar);
	}
	
	public JMenuBar getMenuBar() {
		SessionHolder session = SessionHolder.getInstance();
		if(!session.isAuthenticated()) {
			return defaultMenuBar;
		} else {
			if(loggedMenuBar == null){
				loggedMenuBar = new LoggedMenuBar(resourceMap, controller);
			}
			loggedMenuBar.setLoggedUser(session.getLoggedUser());
			return loggedMenuBar;
		}
	}
	
	public void switchToView(AbstractView.ViewType pViewType, Object args) {
		String viewName = StringUtils.capitalize(pViewType.toString().toLowerCase()) + "Window";
		this.switchToView(viewName, args);
	}
	
	public void switchToView(AbstractView.ViewType pViewType) {
		String viewName = StringUtils.capitalize(pViewType.toString().toLowerCase()) + "Window";
		this.switchToView(viewName, null);
	}
	
	/**
     * Display a given view in the frame
     * 
     * @param pViewType
     *            the view to display
     */
    public void switchToView(String name, Object args) {
    	// The view is loaded automatically with the "*Window" naming convention inside the 
    	// tpenchere.ui.contents package
    	// If the specified view is not found, load the LOGIN page per default
    	String packageName = "tpenchere.ui.contents.";
    	String viewName = packageName + name;
    	if(cachedViews.containsKey(name)) {
    		currentView = cachedViews.get(name);
    	} else {
    		try {				
				currentView = (AbstractView) ClassLoader
						.getSystemClassLoader()
						.loadClass(viewName)
						.newInstance();
				cachedViews.put(name, currentView);
			} catch (ClassNotFoundException cnfe) {
				System.out.println("View "+viewName+" not found ! Relocating to login page");
				this.switchToView(AbstractView.ViewType.LOGIN);
				return;
			} catch (IllegalAccessException iae) {
				iae.printStackTrace();
			} catch (InstantiationException ie) {
				ie.printStackTrace();
			}
    	}
    	
        // if the view needs to be updated
        if(args != null) {
			currentView.updateView(args);
		} else {
			currentView.updateView();			
		}
        this.updateView();

        // display the new view
        setComponent(currentView);
//        setStatusBar(currentView.getStatusBar());
        //setMenuBar(currentView.getMenuBar());
        // remove all JToolbar components before add one
        // setToolBars() should do that but it doesn't, it is a bug from BSAF
//        if (getToolBar() != null) {
//            Container lToolbarPane = getToolBar().getParent();
//            for (Component lCompo : lToolbarPane.getComponents()) {
//                if (lCompo instanceof JToolBar) {
//                    lToolbarPane.remove(lCompo);
//                }
//            }
//        }
//        setToolBars(currentView.getToolbars());
        currentView.revalidate();
        currentView.repaint();
        // avoid a bad frame display
        Window lRootFrame = (Window) getRootPane().getParent();
        if (lRootFrame.getSize().height == 0 || lRootFrame.getSize().width == 0) {
            lRootFrame.pack();
        }
    }

	private class Quit extends AbstractAction {
		public Quit() {
			putValue(NAME, "Quitter");
			putValue(SHORT_DESCRIPTION, "Quitte l'application");
		}
		public void actionPerformed(ActionEvent e) {
			System.exit(0);
		}
	}

	public String getCurrentPanel() {
		return currentPanel;
	}

	public void setCurrentPanel(String currentPanel) {
		this.currentPanel = currentPanel;
	}
	
	/**
	 * Displays an error message
	 * 
	 * @param message
	 */
	public void showError(String message) {
		JOptionPane.showInternalMessageDialog(null, message, "Error", JOptionPane.ERROR_MESSAGE);
	}

	/**
	 * Displays an error message
	 * @param message
	 * @param title
	 */
	public void showError(String message, String title) {
		JOptionPane.showInternalMessageDialog(null, message, title, JOptionPane.ERROR_MESSAGE);
	}

	/**
	 * Refresh the mainWindow component
	 */
	private void updateView() {
		this.setMenuBar(this.getMenuBar());
	}
}
